/* eslint-disable array-callback-return */
/* eslint-disable prefer-destructuring */
"use strict";

/* !
 * from ExternalTemplateRemotesPlugin
 * License: MIT (https://mit-license.org/)
 */
// @ts-expect-error
const extractUrlAndGlobal = require("webpack/lib/util/extractUrlAndGlobal");
// const { RawSource } = require("webpack-sources");

const PLUGIN_NAME = "ExternalTemplateRemotesRspackPlugin";

/**
 * @deprecated rspack 没有afterCodeGeneration这个钩子
 */
class ExternalTemplateRemotesRspackPlugin {
  /**
   * @param {import("webpack").Compiler} compiler
   */
  apply(compiler) {
    compiler.hooks.make.tap(PLUGIN_NAME, (compilation) => {
      /**
       * @type {import("webpack").ExternalModule[]}
       */
      const scriptExternalModules = [];

      compilation.hooks.buildModule.tap(
        PLUGIN_NAME,
        /** @param {import("webpack").ExternalModule} module */
        // @ts-expect-error
        (module) => {
          if (
            module.constructor.name === "ExternalModule" &&
            module.externalType === "script"
          ) {
            scriptExternalModules.push(module);
          }
        },
      );
      // ! rspack 没有这个钩子
      compilation.hooks.afterCodeGeneration.tap(PLUGIN_NAME, () => {
        scriptExternalModules.map((module) => {
          const urlTemplate = extractUrlAndGlobal(module.request)[0];
          const urlExpression = toExpression(urlTemplate);
          const codeGenerationResult =
            /** @type {import("webpack").CodeGenerationResults} */ (
              compilation.codeGenerationResults
            );
          const sourceMap =
            // @ts-expect-error
            codeGenerationResult.get(module).sources;
          const rawSource = /**
           * @type {import("webpack-sources").Source}
           */ (sourceMap.get("javascript"));
          sourceMap.set(
            "javascript",
            new compiler.webpack.sources.RawSource(
              rawSource
                .source()
                .toString()
                .replace(`"${urlTemplate}"`, urlExpression),
            ),
          );
        });
      });
    });
  }
}

/**
 * @param {string} templateUrl
 * @returns {string}
 */
function toExpression(templateUrl) {
  const result = [];
  const current = [];
  let isExpression = false;
  let invalid = false;
  for (const c of templateUrl) {
    if (c === "[") {
      if (isExpression) {
        invalid = true;
        break;
      }
      isExpression = true;
      if (current.length) {
        result.push(`"${current.join("")}"`);
        current.length = 0;
      }
    } else if (c === "]") {
      if (!isExpression) {
        invalid = true;
        break;
      }
      isExpression = false;
      if (current.length) {
        result.push(`${current.join("")}`);
        current.length = 0;
      }
      current.length = 0;
    } else {
      current.push(c);
    }
  }
  if (isExpression || invalid) {
    throw new Error(`Invalid template URL "${templateUrl}"`);
  }
  if (current.length) {
    result.push(`"${current.join("")}"`);
  }
  return result.join(" + ");
}

module.exports = ExternalTemplateRemotesRspackPlugin;
